#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <signal.h> 
#include <stdlib.h>       
#include <string.h>
#include <pthread.h>
//#include <sys/sem.h>
#include <errno.h>
#include <sys/ipc.h>
//#include <sys/msg.h>
#include <sys/timeb.h>
#include <sys/socket.h>
//#include <sys/socketvar.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <semaphore.h>
#include <string.h>
#include <termios.h>
#include <linux/input.h>
#include <semaphore.h>
#include <linux/shm.h>
#include <asm/unistd.h>
#include <sys/poll.h>

/*0,-1,-2,>0*/
int RecvData(const int nSocket,char *pData,const int nSize,const int nTimeOut)
{
		int ret;
		struct pollfd pollflag;
		
	  pollflag.fd     = nSocket;
	  pollflag.events = POLLIN;
  
		ret = poll( &pollflag, 1, nTimeOut*1000 );
		
		if( ret <= 0 )
		{
				return ret;
		}		
		
		ret = recv(nSocket,pData,nSize,0);
		
		if( ret <= 0 )
		{						
				return -2;
		}
		
		return 	ret;	
}

/*0,-1,-2,>0*/
int SendData(const int nSocket,const char *pData,const int nSize,const int nTimeOut)
{
		int ret,num;
		int nCount = 0;	
		struct pollfd pollflag;
		
		do
		{
			  pollflag.fd     = nSocket;
		  	pollflag.events = POLLOUT;
		  	
				ret = poll( &pollflag, 1, nTimeOut*1000 );
				
				if( ret <= 0 )
				{
						return ret;
				}				  	
			
				num = (nSize - nCount) > 2096 ? 2096 : (nSize - nCount);
			
				ret = send( nSocket, pData + nCount, num, 0 );				
			
				if( ret <= 0 )
				{
						return -2;
				}			
					
				nCount += ret;	
		}
		while( nCount <  nSize );
		
		return nCount;
}


int UdpBind(const int nPort)/*-1SOCKET,-2,-3*/
{
		//char    temp[80];
		int 		 iSocket;
		int       	flag=1,len=sizeof(int);	
		socklen_t svrlen;
		int ret, rcvSize, optLen;
		struct sockaddr_in localaddr; 
		
		if( ( iSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP) ) == -1 )
		{
				//WriteLog(__FILE__,__LINE__,"SOCKET");
				return -1;
		}	
		
		setsockopt(iSocket, SOL_SOCKET, SO_REUSEADDR, &flag, len);
		
		if(nPort == 9418)
		{
				optLen = sizeof(rcvSize);
				ret = getsockopt(iSocket, SOL_SOCKET, SO_RCVBUF, &rcvSize, &optLen);
				if(ret < 0)
				{
						printf("org get recv buffer size fail !\n");
						return -11;	
				}
				//printf("org rcvSize = %d\n", rcvSize);
				
				rcvSize = 320 *1024;
				ret = setsockopt(iSocket, SOL_SOCKET, SO_RCVBUF, &rcvSize, optLen);
				if(ret < 0)
				{
						printf("set recv buffer size error !\n");	
						return -12;
				}
				
				ret = getsockopt(iSocket, SOL_SOCKET, SO_RCVBUF, &rcvSize, &optLen);
				if(ret < 0)
				{
						printf("real get recv buffer size fail !\n");
						return -13;	
				}
				//printf("real rcvSize = %d\n", rcvSize);
		}
		
		
		svrlen = sizeof(localaddr);
		memset( (char *)&localaddr, 0x0, svrlen);
		
		localaddr.sin_family      = AF_INET;
		localaddr.sin_addr.s_addr = htonl( INADDR_ANY );
		localaddr.sin_port        = htons( nPort );
		
		if( bind( iSocket,( struct sockaddr * )&localaddr, svrlen ) == -1 )
		{
				//sprintf(temp,"[%d]",nPort);
				//WriteLog(__FILE__,__LINE__,temp);
				close(iSocket);
				return -2;
		}
		
		flag = fcntl( iSocket, F_GETFL, 0 ); 
		if( fcntl( iSocket, F_SETFL, flag | O_NONBLOCK ) == -1 )
		{
				//WriteLog(__FILE__,__LINE__,"");
				close(iSocket);
				return -3;
		}	
		
		return iSocket;
}

int TcpBind(const int nPort)/*-1SOCKET,-2,-3,-4*/
{
		socklen_t             svrlen;
		struct sockaddr_in localaddr; 
		int  sockls; 
		int    flag;	
		
		svrlen = sizeof(localaddr);
		memset( (char *)&localaddr, 0, svrlen);
		
		localaddr.sin_family = AF_INET;
		localaddr.sin_addr.s_addr = htonl( INADDR_ANY );
		localaddr.sin_port = htons( nPort );
					
		if( ( sockls = socket(AF_INET, SOCK_STREAM, 0) )	== -1 )
		{
				//WriteLog(__FILE__,__LINE__,"socket error");
				return -1;		
		}	
		
		flag = fcntl( sockls, F_GETFL, 0 ); 
		if( fcntl( sockls, F_SETFL, flag | O_NONBLOCK ) == -1 )
		{
				//WriteLog(__FILE__,__LINE__, "fcntl error");	
				close(sockls);
		}			
					
		if( bind( sockls,( struct sockaddr * )&localaddr, svrlen ) == -1 )
		{
				//printf("StartServer: Bind failed because daemon already loaded!\n");
				//WriteLog(__FILE__,__LINE__,"StartServer: Bind failed because daemon already loaded!");
				close(sockls);
				return -2;
		}
		
		if( listen( sockls, 10000 ) == -1 )
		{
				//printf("StartServer: Listen sockfd port failed!\n");
				//WriteLog(__FILE__,__LINE__, "StartServer: Listen sockfd port failed!");
				close(sockls);
				return -3;
		} 
		
		flag = fcntl( sockls, F_GETFL, 0 ); 
		if( fcntl( sockls, F_SETFL, flag | O_NONBLOCK ) == -1 )
		{
				//WriteLog(__FILE__,__LINE__, "fcntl error");	
				close(sockls);
				return -4;
		}
			
		return sockls;
}

int connectTo(const char *ip,const int port,const int nTimeOut)
{
		socklen_t             svrlen;
		struct sockaddr_in localaddr; 
		int  sockls; 
		int  ret,flag,error=1;	
		struct pollfd pollflag;
		
		svrlen = sizeof(localaddr);
		memset( (char *)&localaddr, 0, svrlen);
		
		localaddr.sin_family = AF_INET;
		localaddr.sin_addr.s_addr = inet_addr(ip);
		localaddr.sin_port = htons( port );
					
		if( ( sockls = socket(AF_INET, SOCK_STREAM, 0) )	== -1 )
		{
				//WriteLog(__FILE__,__LINE__,"socket error");
				return -1;		
		}
		
		flag = fcntl( sockls, F_GETFL, 0 ); 
		if( fcntl( sockls, F_SETFL, flag | O_NONBLOCK ) == -1 )
		{
				//WriteLog(__FILE__,__LINE__, "fcntl error");	
				close(sockls);
				return -2;
		}
		
		if( connect(sockls,(const struct sockaddr *)&localaddr,svrlen) != 0 )
		{
				if( errno == EINPROGRESS )
				{
						pollflag.fd     = sockls;
		  			pollflag.events = POLLOUT;
		  	
						ret = poll( &pollflag, 1, nTimeOut*1000 );
					
						if( ret <= 0 )
						{
								close(sockls);
								return -3;
						}		
						
						svrlen = sizeof(error);
							
						if( getsockopt(sockls,SOL_SOCKET,SO_ERROR,&error,&svrlen) == -1 )
						{
								close(sockls);
								return -4;
						}		
								
						if( error != 0 )		
						{
								close(sockls);
								return -5;
						}	
				}
				else
				{
						close(sockls);
						return -6;
				}
		}			

		return sockls;	
}


